package com.info.zhiduoduo.alipay.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AccessParams;
import com.alipay.api.domain.AlipayDataBillAccountbookereceiptQueryModel;
import com.alipay.api.domain.AlipayDataBillEreceiptagentApplyModel;
import com.alipay.api.domain.AlipayFundAccountbookCreateModel;
import com.alipay.api.domain.AlipayFundAccountbookQueryModel;
import com.alipay.api.domain.AlipayFundTransCommonQueryModel;
import com.alipay.api.domain.AlipayFundTransPagePayModel;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayUserAgreementPageSignModel;
import com.alipay.api.domain.AlipayUserAgreementQueryModel;
import com.alipay.api.domain.AlipayUserAgreementUnsignModel;
import com.alipay.api.domain.Participant;
import com.alipay.api.request.AlipayDataBillAccountbookereceiptQueryRequest;
import com.alipay.api.request.AlipayDataBillEreceiptagentApplyRequest;
import com.alipay.api.request.AlipayFundAccountbookCreateRequest;
import com.alipay.api.request.AlipayFundAccountbookQueryRequest;
import com.alipay.api.request.AlipayFundTransCommonQueryRequest;
import com.alipay.api.request.AlipayFundTransPagePayRequest;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayUserAgreementPageSignRequest;
import com.alipay.api.request.AlipayUserAgreementQueryRequest;
import com.alipay.api.request.AlipayUserAgreementUnsignRequest;
import com.alipay.api.response.AlipayDataBillAccountbookereceiptQueryResponse;
import com.alipay.api.response.AlipayDataBillEreceiptagentApplyResponse;
import com.alipay.api.response.AlipayFundAccountbookCreateResponse;
import com.alipay.api.response.AlipayFundAccountbookQueryResponse;
import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
import com.alipay.api.response.AlipayFundTransPagePayResponse;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayUserAgreementPageSignResponse;
import com.alipay.api.response.AlipayUserAgreementQueryResponse;
import com.alipay.api.response.AlipayUserAgreementUnsignResponse;
import com.info.zhiduoduo.alipay.config.base.BaseAlipayConfig;
import com.info.zhiduoduo.alipay.constant.AlipayIdentityEnum;
import com.info.zhiduoduo.alipay.constant.AlipayOrderEnum;
import com.info.zhiduoduo.alipay.constant.AlipayPrincipalEnum;
import com.info.zhiduoduo.alipay.model.AliPayReturnDto;
import com.info.zhiduoduo.alipay.model.request.RechargeModel;
import com.info.zhiduoduo.alipay.model.request.TransferModel;
import com.info.zhiduoduo.common.constants.StatusMsg;
import com.info.zhiduoduo.common.exception.SmartException;
import com.info.zhiduoduo.common.utils.ContextUtil;
import com.info.zhiduoduo.common.utils.DateUtil;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.RoundingMode;
import java.util.Date;

import lombok.extern.slf4j.Slf4j;

/**
 * 安全发（人资ISV版）文档: https://opendocs.alipay.com/open/01kwnq
 */
@Service
@Slf4j
public class AliPayApiService {

	/**
	 * 获取接口客户端
	 *
	 * @param alipayConfig 支付宝配置
	 * @return
	 */
	private AlipayClient getAlipayClient(BaseAlipayConfig alipayConfig) {
		return new DefaultAlipayClient(alipayConfig.getAlipayGateway(), alipayConfig.getAppId(), alipayConfig.getAppPrivateKey(), "json",
				alipayConfig.getAlipayCharset(), alipayConfig.getAlipayPublicKey(), alipayConfig.getAlipaySignType());
	}

	/**
	 * 获取接口客户端
	 *
	 * @param isv  平台的支付宝业务类型
	 * @return
	 */
	private AlipayClient getAlipayClient(AlipayPrincipalEnum isv) {
		return getAlipayClient(ContextUtil.getBean(isv.config));
	}

	/**
	 * 获取使用密钥证书的接口客户端
	 *
	 * @param isv
	 * @return
	 * @throws AlipayApiException
	 */
	private DefaultAlipayClient getCertAlipayClient(AlipayPrincipalEnum isv) throws AlipayApiException {
		BaseAlipayConfig alipayConfig = ContextUtil.getBean(isv.config);
		CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
		certAlipayRequest.setServerUrl(alipayConfig.getAlipayGateway());
		certAlipayRequest.setAppId(alipayConfig.getAppId());
		certAlipayRequest.setPrivateKey(alipayConfig.getAppPrivateKey());
		certAlipayRequest.setFormat("json");
		certAlipayRequest.setCharset(alipayConfig.getAlipayCharset());
		certAlipayRequest.setSignType(alipayConfig.getAlipaySignType());
		certAlipayRequest.setCertPath(alipayConfig.getAppCertPublicKeyPath());
		certAlipayRequest.setAlipayPublicCertPath(alipayConfig.getAlipayCertPublicKeyPath());
		certAlipayRequest.setRootCertPath(alipayConfig.getAlipayRootCertPath());
		return new DefaultAlipayClient(certAlipayRequest);
	}

	/**
	 * 支付宝普通App支付
	 *
	 * @param subject
	 * @param payNo
	 * @param money            订单总金额，单位为人民币（元），取值范围为 0.01~100000000.00，精确到小数点后两位。
	 * @param payNotifyUrl     支付回调接口,如果没有手动指定,则使用AlipayPrincipalEnum配置中的接口
	 * @param isvPrincipalEnum
	 * @return
	 */
	public AliPayReturnDto tradeAppPay(String subject, String payNo, String money, String payNotifyUrl,
	                                   AlipayPrincipalEnum isvPrincipalEnum) {
		try {
			BaseAlipayConfig alipayConfig = ContextUtil.getBean(isvPrincipalEnum.config);
			// 参考支付宝文档: https://opendocs.alipay.com/open/54/106370
			//实例化客户端
			AlipayClient alipayClient = getCertAlipayClient(isvPrincipalEnum);
			//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
			AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
			//SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
			AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
			model.setSubject(subject);
			model.setOutTradeNo(payNo);
			model.setTimeoutExpress("30m");
			model.setTotalAmount(money);
			model.setProductCode("QUICK_MSECURITY_PAY");
			request.setBizModel(model);
			// 如果没有手动指定回调接口路径,则使用配置中的接口
			if (StringUtils.isBlank(payNotifyUrl)) {
				request.setNotifyUrl(alipayConfig.getPayNotifyUrl());
			} else {
				request.setNotifyUrl(payNotifyUrl);
			}

			AlipayTradeAppPayResponse response = null;

			//这里和普通的接口调用不同，使用的是sdkExecute
			response = alipayClient.sdkExecute(request);
			log.info("调用alipay SDK, 结果: {}", JSON.toJSONString(response));
			log.info("调用alipay SDK,生成的body: {}", response.getBody()); //就是orderString 可以直接给客户端请求，无需再做处理。

			AliPayReturnDto dto = new AliPayReturnDto();
			dto.setInfo(response.getBody());
			dto.setPayNo(payNo);
			return dto;
		} catch (AlipayApiException e) {
			log.error("支付信息加密失败！", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 用户签约支付宝安全发
	 * 用户协议签约的页面接口
	 * alipay.user.agreement.page.sign
	 *
	 * @param agreementNo      平台的签约号, 唯一值
	 * @param alipayPrincipal
	 * @return
	 */
	public String userAgreementPageSign(String agreementNo, AlipayPrincipalEnum alipayPrincipal) {
		try {
			BaseAlipayConfig alipayConfig = (BaseAlipayConfig) ContextUtil.getBean(alipayPrincipal.config);
			AlipayClient alipayClient = getCertAlipayClient(alipayPrincipal);

			AlipayUserAgreementPageSignRequest request = new AlipayUserAgreementPageSignRequest();
			AlipayUserAgreementPageSignModel model = new AlipayUserAgreementPageSignModel();
			AccessParams accessParams = new AccessParams();
			accessParams.setChannel("QRCODE");
			model.setAccessParams(accessParams);
			model.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
			model.setSignScene("INDUSTRY|SATF_ACC");
			model.setProductCode("FUND_SAFT_SIGN_WITHHOLDING");
			model.setExternalAgreementNo(agreementNo);
			model.setThirdPartyType("PARTNER");
			// model.setPassParams(String.valueOf(alipayPrincipal.id));
			request.setBizModel(model);
			request.setNotifyUrl(alipayConfig.getAgreementSignNotifyUrl());

			AlipayUserAgreementPageSignResponse response = alipayClient.pageExecute(request, "get");
			log.info("调用alipay SDK, userAgreementPageSign结果: {}", JSON.toJSONString(response));
			log.info("调用alipay SDK, userAgreementPageSign生成的body: {}", response.getBody());
			return response.getBody();
		} catch (AlipayApiException e) {
			log.error("调用用户签约接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 用户解约安全发协议
	 * 协议解约接口
	 * alipay.user.agreement.unsign
	 *
	 * @param agreementNo  平台自己的签约号. 与支付宝平台的签约号不一样.
	 * @return
	 */
	public boolean userAgreementUnsign(String agreementNo, String alipayAgreementNo, AlipayPrincipalEnum alipayPrincipal) {
		try {
			AlipayClient alipayClient = getCertAlipayClient(alipayPrincipal);

			AlipayUserAgreementUnsignRequest request = new AlipayUserAgreementUnsignRequest();
			AlipayUserAgreementUnsignModel model = new AlipayUserAgreementUnsignModel();
			model.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
			model.setSignScene("INDUSTRY|SATF_ACC");
			model.setExternalAgreementNo(agreementNo);
			model.setAgreementNo(alipayAgreementNo);
			request.setBizModel(model);

			AlipayUserAgreementUnsignResponse response = alipayClient.certificateExecute(request);
			log.info("调用alipay SDK, userAgreementPageUnsign结果: {}", JSON.toJSONString(response));
			log.info("调用alipay SDK, userAgreementPageUnsign生成的body: {}", response.getBody()); //就是orderString 可以直接给客户端请求，无需再做处理。
			return "10000".equals(response.getCode());
		} catch (AlipayApiException e) {
			log.error("调用用户签约接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 协议查询接口
	 * alipay.user.agreement.query
	 *
	 * @param agreementNo
	 * @param alipayPrincipal
	 * @return
	 */
	public AlipayUserAgreementQueryResponse userAgreementQuery(String agreementNo, AlipayPrincipalEnum alipayPrincipal) {
		try {
			AlipayClient alipayClient = getCertAlipayClient(alipayPrincipal);

			AlipayUserAgreementQueryRequest request = new AlipayUserAgreementQueryRequest();
			AlipayUserAgreementQueryModel model = new AlipayUserAgreementQueryModel();
			model.setThirdPartyType("PARTNER");
			model.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
			model.setSignScene("INDUSTRY|SATF_ACC");
			model.setExternalAgreementNo(agreementNo);
			request.setBizModel(model);
			AlipayUserAgreementQueryResponse response = alipayClient.certificateExecute(request);//通过alipayClient调用API，获得对应的response类
			log.info("调用alipay SDK, userAgreementQuery结果: {}", JSON.toJSONString(response));
			log.info("调用alipay SDK, userAgreementQuery生成的body: {}", response.getBody());
			return response;
		} catch (AlipayApiException e) {
			log.error("调用用户签约查询接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 记账本开通
	 * alipay.fund.accountbook.create
	 */
	public AlipayFundAccountbookCreateResponse fundAccountBookCreate(String alipayUserId, String agreementNo,
	                                                                 AlipayPrincipalEnum alipayPrincipal) {
		try {
			DefaultAlipayClient alipayClient = getCertAlipayClient(alipayPrincipal);
			AlipayFundAccountbookCreateRequest request = new AlipayFundAccountbookCreateRequest();
			AlipayFundAccountbookCreateModel model = new AlipayFundAccountbookCreateModel();
			model.setMerchantUserType("BUSINESS_ORGANIZATION");
			model.setSceneCode("SATF_FUND_BOOK");
			model.setMerchantUserId(alipayUserId);
			JSONObject jo = new JSONObject();
			jo.put("agreement_no", agreementNo);
			model.setExtInfo(jo.toJSONString());

			request.setBizModel(model);
			AlipayFundAccountbookCreateResponse response = alipayClient.certificateExecute(request);
			log.info("调用alipay SDK, fundAccountBookCreate结果: {}", JSON.toJSONString(response));
			return response;
		} catch (AlipayApiException e) {
			log.error("调用记账本开通接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 记账本查询
	 * alipay.fund.accountbook.query
	 */
	public AlipayFundAccountbookQueryResponse fundAccountBookQuery(String accountBookId, String agreementNo,
	                                                               AlipayPrincipalEnum isvPrincipal) {
		// 测试环境, 直接返回, 不调用真正的接口
		if (!ContextUtil.isProd()) return null;
		try {
			DefaultAlipayClient alipayClient = getCertAlipayClient(isvPrincipal);
			AlipayFundAccountbookQueryRequest request = new AlipayFundAccountbookQueryRequest();
			AlipayFundAccountbookQueryModel model = new AlipayFundAccountbookQueryModel();
			model.setAccountBookId(accountBookId);
			model.setSceneCode("SATF_FUND_BOOK");
			JSONObject jo = new JSONObject();
			jo.put("agreement_no", agreementNo);
			model.setExtInfo(jo.toJSONString());

			request.setBizModel(model);
			AlipayFundAccountbookQueryResponse response = alipayClient.certificateExecute(request);
			log.info("调用alipay SDK, fundAccountBookQuery结果: {}", JSON.toJSONString(response));
			return response;
		} catch (AlipayApiException e) {
			log.error("调用记账本开通接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 记账本充值，资金专款拨入的有密页面接口
	 * alipay.fund.trans.page.pay
	 */
	public String fundTransPagePay(RechargeModel rechargeModel, AlipayPrincipalEnum alipayPrincipal) {
		try {
			BaseAlipayConfig alipayConfig = ContextUtil.getBean(alipayPrincipal.config);
			DefaultAlipayClient alipayClient = getCertAlipayClient(alipayPrincipal);
			AlipayFundTransPagePayRequest request = new AlipayFundTransPagePayRequest();
			AlipayFundTransPagePayModel model = new AlipayFundTransPagePayModel();
			model.setOutBizNo(rechargeModel.getOrderNo());
			model.setTransAmount(rechargeModel.getTransAmount().setScale(2, RoundingMode.DOWN).toString());
			model.setProductCode("FUND_ACCOUNT_BOOK");
			model.setBizScene("SATF_DEPOSIT");
			model.setRemark(rechargeModel.getRemark());
			model.setOrderTitle(rechargeModel.getOrderTitle());
			model.setTimeExpire(DateUtil.getString(DateUtil.addMinute(new Date(), 30))); // 30分钟过期
			Participant payee = new Participant();
			payee.setIdentity(rechargeModel.getAlipayUserId());
			payee.setIdentityType(AlipayIdentityEnum.USER_ID.code);
			JSONObject payeeExt = new JSONObject();
			payeeExt.put("agreement_no", rechargeModel.getAgreementNo());
			payeeExt.put("account_book_id", rechargeModel.getAccountBookId());
			payeeExt.put("accountbook_scene_code", "SATF_FUND_BOOK");
			payee.setExtInfo(payeeExt.toJSONString());
			model.setPayeeInfo(payee);

			request.setBizModel(model);
			AlipayFundTransPagePayResponse response = alipayClient.pageExecute(request, "get");
			log.info("调用alipay SDK, fundTransPagePay结果: {}", JSON.toJSONString(response));
			return response.getBody();
		} catch (AlipayApiException e) {
			log.error("调用记账本充值接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 基于记账本单笔代发到支付宝账户
	 * 资金无密批量代发接口 alipay.fund.trans.uni.transfer
	 *
	 * @param transferModel
	 * @param alipayPrincipal
	 * @return
	 */
	public AlipayFundTransUniTransferResponse fundTransUniTransfer(TransferModel transferModel, AlipayPrincipalEnum alipayPrincipal) {
		// 测试环境, 直接返回, 不调用真正的接口
		if (!ContextUtil.isProd()) {
			AlipayFundTransUniTransferResponse response = new AlipayFundTransUniTransferResponse();
			response.setOrderId("TEST_SUCCESS_00000000000");
			response.setPayFundOrderId("TEST_SUCCESS_00000000000");
			response.setStatus("SUCCESS");
			response.setMsg("Success");
			return response;
		}
		try {
			BaseAlipayConfig alipayConfig = ContextUtil.getBean(alipayPrincipal.config);
			DefaultAlipayClient alipayClient = getCertAlipayClient(alipayPrincipal);
			AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();

			AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
			model.setProductCode("SINGLE_TRANSFER_NO_PWD");
			model.setBizScene("ENTRUST_TRANSFER");
			model.setTransAmount(transferModel.getTransAmount().setScale(2, RoundingMode.DOWN).toString());
			model.setOutBizNo(transferModel.getOrderNo());
			model.setOrderTitle(transferModel.getOrderTitle());
			model.setRemark(transferModel.getOrderRemark());
			JSONObject businessParams = new JSONObject();
			businessParams.put("withdraw_timeliness", "T0");
			model.setBusinessParams(businessParams.toJSONString());
			// 付款方信息
			Participant payer = new Participant();
			payer.setIdentityType(AlipayIdentityEnum.ACCOUNT_BOOK_ID.code);
			payer.setIdentity(transferModel.getAccountBookId());
			JSONObject jo = new JSONObject();
			jo.put("agreement_no", transferModel.getAlipayAgreementNo());
			jo.put("accountbook_scene_code", "SATF_FUND_BOOK");
			payer.setExtInfo(jo.toJSONString());
			model.setPayerInfo(payer);
			// 收款方信息
			model.setPayeeInfo(transferModel.getPayeeInfo().toPayee());

			request.setBizModel(model);
			log.info("调用alipay SDK, fundTransUniTransfer请求参数: {}", JSON.toJSONString(request));
			AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
			log.info("调用alipay SDK, fundTransUniTransfer结果: {}", JSON.toJSONString(response));
			return response;
		} catch (AlipayApiException e) {
			log.error("调用免密转账接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 基于记账本调拨、转账
	 * 记账本之间相互调拨
	 * 资金专款拨入接口 alipay.fund.trans.uni.transfer
	 * <p> 应用于多个记账本之间的转账流程。
	 *
	 * @param transferModel
	 * @param isvPrincipal
	 * @return
	 */
	public AlipayFundTransUniTransferResponse fundTransUniTransferAllocation(TransferModel transferModel,
	                                                                         AlipayPrincipalEnum isvPrincipal) {
		// 测试环境, 直接返回, 不调用真正的接口
		if (!ContextUtil.isProd()) {
			AlipayFundTransUniTransferResponse response = new AlipayFundTransUniTransferResponse();
			response.setOutBizNo(transferModel.getOrderNo());
			response.setOrderId("TEST_SUCCESS_00000000000");
			response.setPayFundOrderId("TEST_SUCCESS_00000000000");
			response.setStatus("SUCCESS");
			response.setMsg("Success");
			return response;
		}
		try {
			DefaultAlipayClient alipayClient = getCertAlipayClient(isvPrincipal);
			AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
			AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
			model.setProductCode("SINGLE_TRANSFER_NO_PWD");
			model.setBizScene("ENTRUST_ALLOCATION");
			model.setTransAmount(transferModel.getTransAmount().setScale(2, RoundingMode.DOWN).toString());
			model.setOutBizNo(transferModel.getOrderNo());
			model.setOrderTitle(transferModel.getOrderTitle());
			model.setRemark(transferModel.getOrderRemark());
			// 付款方信息
			Participant payer = new Participant();
			payer.setIdentityType(AlipayIdentityEnum.ACCOUNT_BOOK_ID.code);
			payer.setIdentity(transferModel.getAccountBookId());
			JSONObject payerExt = new JSONObject();
			payerExt.put("agreement_no", transferModel.getAlipayAgreementNo());
			payerExt.put("accountbook_scene_code", "SATF_FUND_BOOK");
			payer.setExtInfo(payerExt.toJSONString());
			model.setPayerInfo(payer);
			// 收款方信息
			model.setPayeeInfo(transferModel.getPayeeInfo().toPayee());

			request.setBizModel(model);
			log.info("调用alipay SDK, fundTransUniTransferAllocation请求参数: {}", JSON.toJSONString(request));
			AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
			log.info("调用alipay SDK, fundTransUniTransferAllocation结果: {}", JSON.toJSONString(response));
			return response;
		} catch (AlipayApiException e) {
			log.error("调用免密转账充值接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 充值,转账,代付账单结果查询
	 *
	 * @param orderEnum       业务类型: 1:委托人给自己充值 2:委托人转账给受托人 3:受托人代付到户 4:受托人退款给委托人
	 * @param orderNo          平台自己的账单编号
	 * @param alipayPrincipal
	 * @return
	 */
	public AlipayFundTransCommonQueryResponse fundTransCommonQuery(AlipayOrderEnum orderEnum, String orderNo,
	                                                               AlipayPrincipalEnum alipayPrincipal) {
		// 测试环境, 直接返回, 不调用真正的接口
		if (!ContextUtil.isProd()) {
			AlipayFundTransCommonQueryResponse response = new AlipayFundTransCommonQueryResponse();
			response.setOrderId("TEST_SUCCESS_00000000000");
			response.setPayFundOrderId("TEST_SUCCESS_00000000000");
			response.setStatus("SUCCESS");
			response.setMsg("Success");
			response.setPayDate(DateUtil.getString(new Date()));
			return response;
		}

		try {
			DefaultAlipayClient alipayClient = getCertAlipayClient(alipayPrincipal);
			AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();

			AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();
			model.setOutBizNo(orderNo);
			model.setProductCode(orderEnum.productCode);
			model.setBizScene(orderEnum.bizScene);

			request.setBizModel(model);
			AlipayFundTransCommonQueryResponse response = alipayClient.certificateExecute(request);
			log.info("调用alipay SDK, fundTransCommonQuery结果: {}", JSON.toJSONString(response));
			return response;
		} catch (AlipayApiException e) {
			log.error("调用免密转账接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}

	}

	/**
	 * ISV代理商户申请资⾦业务回单openapi.
	 * ISV代理商户，申请商户的资⾦业务回单。
	 * 电⼦签章申请分两个步骤：
	 * 1、使⽤alipay.data.bill.ereceiptagent.apply创建申请，并获取file_id信息。
	 * 2、等待⼀段时间后，使⽤file_id和agreement_no查询 alipay.data.bill.accountbookereceipt.query申请信息。
	 * 单个申请建议每5分钟查询⼀次状态，汇总 （⽇/⽉）回单建议20分钟查询⼀次。⽉初回单⽣成较慢，
	 * 请耐⼼等待（汇总回单在⽉初申请需要等待 ⼏个⼩时） 注：申请成功，并不代表明细查询的流⽔⼀定存在。如果流⽔不存在，在查询时将会提示。
	 *
	 * @param alipayAgreementNo 支付宝平台的协议号
	 * @param fundOrderId       支付宝系统的资金单号
	 * @param alipayPrincipal   isv主体
	 * @return
	 */
	public AlipayDataBillEreceiptagentApplyResponse billEReceiptAgentApply(String alipayAgreementNo, String fundOrderId,
	                                                                       AlipayPrincipalEnum alipayPrincipal) {
		try {
			DefaultAlipayClient alipayClient = getCertAlipayClient(alipayPrincipal);
			AlipayDataBillEreceiptagentApplyRequest request = new AlipayDataBillEreceiptagentApplyRequest();

			AlipayDataBillEreceiptagentApplyModel model = new AlipayDataBillEreceiptagentApplyModel();
			model.setType("FUND_DETAIL");
			model.setKey(fundOrderId);
			model.setAgreementNo(alipayAgreementNo);

			request.setBizModel(model);
			AlipayDataBillEreceiptagentApplyResponse response = alipayClient.certificateExecute(request);
			log.info("调用alipay SDK, billEReceiptAgentApply结果: {}", JSON.toJSONString(response));
			return response;
		} catch (AlipayApiException e) {
			log.error("调用免密转账接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

	/**
	 * 通过上面的
	 * {@link AliPayApiService#billEReceiptAgentApply(java.lang.String, java.lang.String, com.info.zhiduoduo.alipay.constant.AlipayPrincipalEnum)}
	 * 方法获取到fileId后，再调用此方法下载回单文件。
	 *
	 * @param alipayAgreementNo 支付宝平台的协议号
	 * @param fileId            文件id
	 * @param alipayPrincipal   isv主体
	 * @return
	 */
	public AlipayDataBillAccountbookereceiptQueryResponse billAccountbookEreceiptQuery(String alipayAgreementNo, String fileId,
	                                                                                   AlipayPrincipalEnum alipayPrincipal) {
		try {
			DefaultAlipayClient alipayClient = getCertAlipayClient(alipayPrincipal);
			AlipayDataBillAccountbookereceiptQueryRequest request = new AlipayDataBillAccountbookereceiptQueryRequest();

			AlipayDataBillAccountbookereceiptQueryModel model = new AlipayDataBillAccountbookereceiptQueryModel();
			model.setFileId(fileId);
			model.setAgreementNo(alipayAgreementNo);

			request.setBizModel(model);
			AlipayDataBillAccountbookereceiptQueryResponse response = alipayClient.certificateExecute(request);
			log.info("调用alipay SDK, billAccountbookEreceiptQuery结果: {}", JSON.toJSONString(response));
			return response;
		} catch (AlipayApiException e) {
			log.error("调用免密转账接口报错", e);
			throw SmartException.of(StatusMsg.StatusMsg_199);
		}
	}

}
